package com.tongzhan.service.impl;

import com.tongzhan.base.PageInfo;
import com.tongzhan.base.Return;
import com.tongzhan.data.vo.LeaveVO;
import com.tongzhan.entity.User;
import com.tongzhan.entity.religion.Leave;
import com.tongzhan.entity.religion.ModuleSign;
import com.tongzhan.repository.UserRepository;
import com.tongzhan.repository.religion.LeaveRepository;
import com.tongzhan.repository.religion.ModuleSignRepository;
import com.tongzhan.service.LeaveService;
import com.tongzhan.utils.DateSwitcher;
import com.tongzhan.utils.SnowFlakeUtils;
import com.tongzhan.utils.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

@Slf4j
@Service
public class LeaveServiceImpl implements LeaveService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private LeaveRepository leaveRepository;

    @Autowired
    private ModuleSignRepository signRepository;

    @Override
    public Return leaveApplication(String userId, Leave leave) {
        String leaveCode = leave.getLeaveCode();
        if (StringUtils.isEmpty(leaveCode)) {
            //用户
            User user = userRepository.findByPrimaryKey(userId);
            if (user == null) {
                return new Return(Return.FAIL, "用户不存在");
            }
            leave.setUserName(user.getUserName());
            leave.setRealName(user.getRealName());
            leave.setStreetCode(user.getStreetCode());
            leave.setStreetName(user.getStreetName());
            leave.setReligionCode(user.getReligionCode());
            leave.setReligionName(user.getReligionName());
            leave.setSiteCode(user.getSiteCode());
            leave.setSiteName(user.getSiteName());
            leave.setReligionCode(user.getReligionCode());
            leave.setReligionName(user.getReligionName());
            //新增
            leave.setTime(LocalDateTime.now());
            leave.setGroupExamine("待审核");
            leave.setCancelState("未销假");
            //生成请销假编码
            SnowFlakeUtils snow = new SnowFlakeUtils(4, 2);
            leave.setLeaveCode(String.valueOf(snow.nextId()));
            leaveRepository.insert(leave);
            //角标提醒：民宗局、root、镇街道、宗教团体、村社区
            Query query = new Query();
            List<String> codes = Arrays.asList("00", "01", "03");
            query.addCriteria(Criteria.where("DutiesCode").in(codes));
            List<ModuleSign> signList = signRepository.findAll(query);
            //镇街道
            List<ModuleSign> streetList = signRepository.findAll(new Query().addCriteria(Criteria.where("DutiesCode").is("02")
                    .and("StreetCode").is(leave.getStreetCode())));
            //村社区
            List<ModuleSign> villageList = signRepository.findAll(new Query().addCriteria(Criteria.where("DutiesCode").is("05")
                    .and("StreetCode").is(leave.getVillageCode())));
            signList.addAll(streetList);
            signList.addAll(villageList);
            if (!CollectionUtils.isEmpty(signList)) {
                for (ModuleSign sign : signList) {
                    //请销假角标加一
                    sign.setLeave(sign.getLeave() + 1);
                    signRepository.updateByPrimaryKey(sign);
                }
            }
        } else {
            //修改
            Leave updateLeave = leaveRepository.findByPrimaryKey(leaveCode);
            if (updateLeave != null) {
                leave.setOverTime(updateLeave.getOverTime());
                leave.setTime(updateLeave.getTime());
                leave.setCancelState(updateLeave.getCancelState());
                leave.setGroupExamine(updateLeave.getGroupExamine());
                leave.setUserName(updateLeave.getUserName());
                leave.setRealName(updateLeave.getRealName());
                leave.setStreetCode(updateLeave.getStreetCode());
                leave.setStreetName(updateLeave.getStreetName());
                leave.setReligionCode(updateLeave.getReligionCode());
                leave.setReligionName(updateLeave.getReligionName());
                leave.setSiteCode(updateLeave.getSiteCode());
                leave.setSiteName(updateLeave.getSiteName());
                leave.setReligionCode(updateLeave.getReligionCode());
                leave.setReligionName(updateLeave.getReligionName());
            }
            leave.setUpdateTime(LocalDateTime.now());
            leaveRepository.updateByPrimaryKey(leave);
        }
        return new Return(Return.SUCCESS, "操作成功");
    }

    @Override
    public Return getLeaveList(String userId, Integer page, Integer size, String religionCode, String time, String state) {
        //用户信息
        User user = userRepository.findByPrimaryKey(userId);
        if (user == null) {
            return new Return(Return.FAIL, "用户不存在");
        }
        //查询条件
        Query query = new Query();
        query.with(Sort.by(Sort.Direction.DESC, "Time"));
        if (StringUtils.isNotEmpty(religionCode)) {
            query.addCriteria(Criteria.where("ReligionCode").is(religionCode));
        }
        if (StringUtils.isNotEmpty(state)) {
            query.addCriteria(Criteria.where("GroupExamine").is(state));
        }
        if (StringUtils.isNotEmpty(time)) {
            String first = time + "-01";
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            try {
                LocalDateTime start = DateSwitcher.getMinTime(LocalDate.parse(first, dtf).atStartOfDay());
                LocalDateTime end = DateSwitcher.getMaxTime(start.with(TemporalAdjusters.lastDayOfMonth()));
                query.addCriteria(Criteria.where("StartTime").lte(end)
                        .orOperator(Criteria.where("EndTime").gte(start)));
            } catch (Exception e) {
                return new Return(Return.FAIL, "日期格式不正确，为 yyyy-MM");
            }
        }
        //权限编码
        String dutiesCode = user.getDutiesCode();
        if ("02".equals(dutiesCode) || ThreadLocalUtil.STREET_CODE.equals(dutiesCode)) {
            //街道
            query.addCriteria(Criteria.where("StreetCode").is(user.getStreetCode()));
        } else if ("03".equals(dutiesCode)) {
            //宗教
            query.addCriteria(Criteria.where("ReligionCode").is(user.getReligionCode()));
        } else if ("05".equals(dutiesCode) || ThreadLocalUtil.VILLAGE_CODE.equals(dutiesCode)) {
            //村社区
            query.addCriteria(Criteria.where("VillageCode").is(user.getVillageCode()));
        } else if ("04".equals(dutiesCode) || "07".equals(dutiesCode)) {
            //场所、民间信仰点
            query.addCriteria(Criteria.where("SiteCode").is(user.getSiteCode()));
        }
        //请销假列表
        Page<Leave> leavePage = leaveRepository.findPage(query, PageRequest.of(page - 1, size));
        //VO
        List<LeaveVO> vos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(leavePage.getContent())) {
            for (Leave leave : leavePage.getContent()) {
                LeaveVO vo = new LeaveVO();
                vo.setLeaveCode(leave.getLeaveCode());
                vo.setUserName(leave.getUserName());
                vo.setRealName(leave.getLeaveName());
                vo.setSiteCode(leave.getSiteCode());
                vo.setSiteName(leave.getSiteName());
                vo.setReligionCode(leave.getReligionCode());
                vo.setReligionName(leave.getReligionName());
                vo.setStartTime(leave.getStartTime());
                vo.setEndTime(leave.getEndTime());
                vo.setGroupExamine(leave.getGroupExamine());
                vo.setCancelState(leave.getCancelState());
                vo.setDescribe(leave.getDescribe());
                vos.add(vo);
            }
        }
        //重置请销假角标
        ModuleSign sign = signRepository.findByPrimaryKey(userId);
        if (sign != null) {
            sign.setLeave(0L);
            signRepository.updateByPrimaryKey(sign);
        }
        //分页信息
        PageInfo pageInfo = new PageInfo();
        pageInfo.setPage(page);
        pageInfo.setSize(vos.size());
        pageInfo.setTotal(leavePage.getTotalElements());
        //封装返回数据
        Map<String, Object> map = new HashMap<>();
        map.put("leaveList", vos);
        map.put("pageInfo", pageInfo);
        return new Return(map);
    }

    @Override
    public Return leaveExamine(String userId, String leaveCode, String opinion) {
        //用户信息
        User user = userRepository.findByPrimaryKey(userId);
        if (user == null) {
            return new Return(Return.FAIL, "用户不存在");
        }
        //请销假信息
        Leave leave = leaveRepository.findByPrimaryKey(leaveCode);
        if ("03".equals(user.getDutiesCode())) {
            //宗教团体审核
            leave.setGroupExamine(opinion);
        } else {
            return new Return(Return.FAIL, "暂无审核权限");
        }
//        if ("00".equals(user.getSiteDutiesCode()) || "01".equals(user.getDutiesCode())) {
//            //民宗局或Root审核
//            leave.setDirectorExamine(opinion);
//        }
        leave.setUpdateTime(LocalDateTime.now());
        leaveRepository.updateByPrimaryKey(leave);
        return new Return(Return.SUCCESS, "操作成功");
    }

    @Override
    public Return agreeLeave(String leaveCode) {
        Leave leave = leaveRepository.findByPrimaryKey(leaveCode);
        if (leave != null) {
            leave.setOverTime(LocalDateTime.now().toString());
            leave.setCancelState("已销假");
            leave.setUpdateTime(LocalDateTime.now());
            leaveRepository.updateByPrimaryKey(leave);
        }
        return new Return(Return.SUCCESS, "销假成功");
    }

    @Override
    public Return deleteLeave(String leaveCode) {
        leaveRepository.deletePrimaryKey(leaveCode);
        return new Return(Return.SUCCESS, "删除成功");
    }
}
